﻿// -----------------------------------------------------------------------
// <copyright file="RadioController.cs" company="Abyssalsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace Metal.Player.Radio
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Reflection;
    using System.Text;
    using System.Windows.Forms;
    using System.Xml;
    using Metal.Config;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class RadioController
    {
        #region Members

        /// <summary>Reference to our view</summary>
        private static IRadioView view;

        /// <summary>The data set used to bind our list</summary>
        private static DataSet dataSet;

        /// <summary>The data set used to bind categories</summary>
        private static DataSet categoriesDataSet;

        /// <summary>Stores the current list name</summary>
        private static string currentListName;

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the RadioController class.
        /// </summary>
        /// <param name="iView">Interface to communicate with the mask</param>
        public RadioController(IRadioView iView)
        {
            view = iView;
            this.SubscribeToViewEvents();
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the list data set
        /// </summary>
        public static DataSet ListDataSet
        {
            get
            {
                return dataSet;
            }

            set
            {
                dataSet = value;
            }
        }

        /// <summary>
        /// Gets or sets the categories data set
        /// </summary>
        public static DataSet CategoriesDataSet
        {
            get
            {
                return categoriesDataSet;
            }

            set
            {
                categoriesDataSet = value;
            }
        }

        /// <summary>
        /// Gets or sets the interface to communicate with the mask
        /// </summary>
        internal static IRadioView CurrentView
        {
            get
            {
                return view;
            }

            set
            {
                view = value;
            }
        }

        /// <summary>
        /// Gets or sets the current list name
        /// </summary>
        internal static string CurrentFileName
        {
            get
            {
                return currentListName;
            }

            set
            {
                currentListName = value;
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Save the current list
        /// </summary>
        public static void SaveCurrentList()
        {
            try
            {
                XmlWriterSettings xmlSettings = new XmlWriterSettings();
                xmlSettings.Indent = true;
                xmlSettings.NewLineOnAttributes = true;

                XmlWriter xmlList;
                xmlList = XmlWriter.Create(Metal.Config.Paths.RadioListsFolder + CurrentFileName + ".xml", xmlSettings);
                ListDataSet.WriteXml(xmlList);
                xmlList.Close();
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Select specific playlists row
        /// </summary>
        /// <param name="columnIndex">The column that contains our search key</param>
        /// <param name="value">Search for this row value</param>
        public static void SelectRow(int columnIndex, string value)
        {
            // Select our new list
            int index = 0;
            for (int i = 0; i < CategoriesDataSet.Tables[0].Rows.Count; i++)
            {
                if (CategoriesDataSet.Tables[0].Rows[i][columnIndex].ToString() == value)
                {
                    index = i;
                }
            }

            CurrentView.SelectCategoriesRow = index;
        }

        /// <summary>
        /// Sets the current view (audio / video form)
        /// </summary>
        /// <param name="iView">The view which we must control</param>
        public void SetCurrentView(IRadioView iView)
        {
            CurrentView = iView;
        }

        #endregion

        #region Private methods

        /// <summary>
        /// Subscribe to events defined in the view
        /// </summary>
        private void SubscribeToViewEvents()
        {
            view.MaskLoad += new EventHandler(this.OnMaskLoad);
            view.MaskClose += new EventHandler(this.OnMaskClose);
            view.ControlAdded += new System.Windows.Forms.ControlEventHandler(this.OnControlAdded);
        }

        /// <summary>
        /// Do something when the user select a item in playlist
        /// </summary>
        private void ListClick()
        {
            SelectRow(2, RadioController.CurrentFileName);
        }

        /// <summary>
        /// Open selected list
        /// </summary>
        private void CategoriesClick()
        {
            try
            {
                if (RadioController.CurrentView.CategoriesSelectedRow != null)
                {
                    // Load selected list in the playlist
                    ListDataSet.Clear();
                    ListDataSet.ReadXml(RadioController.CurrentView.CategoriesSelectedRow.Cells[1].Value.ToString());
                    CurrentFileName = RadioController.CurrentView.CategoriesSelectedRow.Cells[2].Value.ToString();

                    // Update
                    view.ListDataSet = ListDataSet;
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Play selected file
        /// </summary>
        private void ListDoubleClick()
        {
            try
            {
                if (RadioController.CurrentView.ListSelectedRow != null)
                {
                    // Set the radio name, in case the streaming does not return ID3 tags
                    Core.Player.MediaInfo.RadioName = RadioController.view.ListSelectedRow.Cells[2].Value.ToString();
                    Core.Player.Playback.Instance.Open(RadioController.view.ListSelectedRow.Cells[1].Value.ToString());
                    Core.Player.Playback.Instance.Play();
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Load last playlist
        /// </summary>
        private void LoadLastList()
        {
            try
            {
                CurrentFileName = Settings.Instance.GetValue("LastSettings.LastRadioList", "Default list");

                // Load list data set
                ListDataSet = new DataSet();

                // Get the dataset with all neccessary columns (loaded from theme xml)
                ListDataSet = CurrentView.ListDataSet;

                // Load last playlist in our dataset
                ListDataSet.ReadXml(Metal.Config.Paths.RadioListsFolder + Settings.Instance.GetValue("LastSettings.LastRadioList", "Default list") + ".xml");

                // Update
                CurrentView.ListDataSet = ListDataSet;
            }
            catch
            {
                // We can ignore it I think...
            }
        }

        /// <summary>
        /// Load the available lists
        /// </summary>
        private void LoadListOfCategories()
        {
            try
            {
                // Load the list of playlists data set
                CategoriesDataSet = new DataSet();

                // Get the dataset with all neccessary columns (loaded from theme xml)
                CategoriesDataSet = view.CategoriesDataSet;

                string[] files = System.IO.Directory.GetFiles(Metal.Config.Paths.RadioListsFolder);

                int nrOfLists = 0;

                foreach (string file in files)
                {
                    CategoriesDataSet.Tables[0].Rows.Add(nrOfLists, file, System.IO.Path.GetFileNameWithoutExtension(file));
                    nrOfLists++;
                }

                // Update
                CurrentView.CategoriesDataSet = CategoriesDataSet;

                SelectRow(2, RadioController.CurrentFileName);
            }
            catch
            {
            }
        }

        #endregion

        #region Mask events

        /// <summary>
        /// This method is called when the mask is loaded.
        /// </summary>
        /// <param name="sender">Object sender</param>
        /// <param name="e">Event arguments</param>
        private void OnMaskLoad(object sender, EventArgs e)
        {
            try
            {
                // Load last playlist
                this.LoadLastList();

                // Load the list of playlists
                this.LoadListOfCategories();

                // Show / hide list of playlists
                if (Settings.Instance.GetValue("LastSettings.ShowListOfCategories", false) == true)
                {
                    CurrentView.CategoriesVisible = true;
                }
                else
                {
                    CurrentView.CategoriesVisible = false;
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// This method is called when the mask is closed.
        /// </summary>
        /// <param name="sender">Object sender</param>
        /// <param name="e">Event arguments</param>
        private void OnMaskClose(object sender, EventArgs e)
        {
            try
            {
                // Save playlist name
                Settings.Instance.SetValue("LastSettings.LastRadioList", CurrentFileName);

                // Write some close logic here.
                SaveCurrentList();
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// This method is called when a control is added on the mask
        /// </summary>
        /// <param name="sender">Object sender</param>
        /// <param name="e">Event arguments</param>
        private void OnControlAdded(object sender, System.Windows.Forms.ControlEventArgs e)
        {
            try
            {
                if (e.Control.GetType() == typeof(Gui.Controls.MetalList))
                {
                    e.Control.Click += new EventHandler(this.OnListClick);
                    e.Control.DoubleClick += new EventHandler(this.OnListDoubleClick);
                    e.Control.MouseDown += new MouseEventHandler(this.OnMouseDown);
                    if ((e.Control as Gui.Controls.MetalList).ContextMenuStrip != null)
                    {
                        (e.Control as Gui.Controls.MetalList).ContextMenuStrip.ItemClicked += new ToolStripItemClickedEventHandler(this.OnContextMenuClick);
                    }
                }
                else if (e.Control.GetType() == typeof(Gui.Controls.MetalPanel))
                {
                    e.Control.ControlAdded += new System.Windows.Forms.ControlEventHandler(this.OnControlAdded);
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        #endregion

        #region Controls events

        /// <summary>
        /// This event occurs when the user clicks on menu
        /// </summary>
        /// <param name="sender">Sender object</param>
        /// <param name="e">ToolStripItem event args</param>
        private void OnContextMenuClick(object sender, ToolStripItemClickedEventArgs e)
        {
            try
            {
                string methodName = e.ClickedItem.Tag.ToString();

                // Call the method via reflection
                Type thisType = typeof(RadioLogic);
                System.Reflection.MethodInfo theMethod = thisType.GetMethod(methodName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
                if (theMethod != null)
                {
                    theMethod.Invoke(RadioLogic.Instance, null);
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// This event occurs on mouse down
        /// </summary>
        /// <param name="sender">Object sender</param>
        /// <param name="e">Event args</param>
        private void OnMouseDown(object sender, MouseEventArgs e)
        {
            try
            {
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// This event occurs on click event
        /// </summary>
        /// <param name="sender">Object sender</param>
        /// <param name="e">Event args</param>
        private void OnListClick(object sender, EventArgs e)
        {
            try
            {
                Type thisType = typeof(RadioController);
                MethodInfo theMethod = thisType.GetMethod(((Gui.Controls.MetalList)sender).Name + "Click", BindingFlags.NonPublic | BindingFlags.Instance);
                if (theMethod != null)
                {
                    theMethod.Invoke(this, null);
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// This event occurs on DoubleClick event
        /// </summary>
        /// <param name="sender">Object sender</param>
        /// <param name="e">Event args</param>
        private void OnListDoubleClick(object sender, EventArgs e)
        {
            try
            {
                Type thisType = typeof(RadioController);
                MethodInfo theMethod = thisType.GetMethod(((Gui.Controls.MetalList)sender).Name + "DoubleClick", BindingFlags.NonPublic | BindingFlags.Instance);
                if (theMethod != null)
                {
                    theMethod.Invoke(this, null);
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        #endregion
    }
}
